/*
 * FlatBuffers-based serialization API test.
 *
 * Perform the same set of updates twice, once using the DDlogRecord-based
 * commit method, and once using FlatBuffers-based commit.  Write updates to
 * two different files that can be diffed by the test script.
 */

import java.io.IOException;
import java.util.*;
import java.lang.RuntimeException;
import java.math.BigInteger;
import java.util.Arrays;
import java.io.PrintStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/* Generic DDlog API shared by all programs. */
import ddlogapi.DDlogAPI;
import ddlogapi.DDlogConfig;
import ddlogapi.DDlogCommand;
import ddlogapi.DDlogRecCommand;
import ddlogapi.DDlogRecord;
import ddlogapi.DDlogException;

/* Additional program-specific bindings generated by `ddlog`. */
import ddlog.typesTest.*;

public class Test {
    private final DDlogAPI api;
    private final PrintStream fb_file;
    private final PrintStream query_file;
    private PrintStream rec_file;

    Test() throws IOException, DDlogException {
        /* Create an instance of the DDlog program with one worker thread. */
        this.api = new DDlogAPI(new DDlogConfig(1, false, 0, DDlogConfig.selfProfiling()), false);
        api.enableCpuProfiling(true);
        api.enableChangeProfiling(true);
        api.recordCommands("replay.dat", false);

        this.fb_file  = new PrintStream("fb.dump");
        this.query_file  = new PrintStream("query.dump");
    }

    // typedef tuple = (bool, bit<8>, string)
    private String printTuple(Tuple3__bool__bit_8___stringReader t) {
        return "(" + t.a0() + ", " + t.a1() + ", \"" + t.a2() + "\")";
    }

    // typedef mtuple = (bit<32>, string)
    private String printMTuple(Tuple2__bit_32___stringReader t) {
        return "(" + t.a0() + ", \"" + t.a1() + "\")";
    }

    private String printNI(NIReader v) {
        List<Tuple3__bool__bit_8___stringReader> vs = v.v();
        ArrayList<String> strings = new ArrayList<String>(vs.size());
        vs.forEach((t) -> strings.add(printTuple(t)));
        return "NI{[" + String.join(", ",strings) + "]}";
    }

    private String printQI(QIReader v) {
        List<Tuple2__bit_32___stringReader> vs = v.m();
        ArrayList<String> vs_strs = new ArrayList<String>(vs.size());
        vs.forEach((t) -> {
            vs_strs.add(t.a0() + "=>\"" + t.a1() + "\"");
        });
        return "QI{{" + String.join(", ", vs_strs) + "}}";
    }

    private String printTI(TIReader v) {
        ddlog_std_Option__bit_32_Reader m = (ddlog_std_Option__bit_32_Reader)(v).m();
        if (m instanceof ddlog_std_Option__bit_32_Reader.ddlog_std_Some) {
            return "TI{ddlog_std::Some{" + ((ddlog_std_Option__bit_32_Reader.ddlog_std_Some)m).x() + "}}";
        } else {
            return "TI{ddlog_std::None{}}";
        }
    }

    private String printWI(WIReader v) {
        ddlog_std_Option__ManyReader m = (ddlog_std_Option__ManyReader)(v).m();
        if (m instanceof ddlog_std_Option__ManyReader.ddlog_std_Some) {
            return "WI{ddlog_std::Some{" + printMany(((ddlog_std_Option__ManyReader.ddlog_std_Some)m).x()) + "}}";
        } else {
            return "WI{ddlog_std::None{}}";
        }
    }

    private String printXI(XIReader v) {
        List<ManyReader> m = v.m();
        ArrayList<String> strings = new ArrayList<String>(m.size());
        m.forEach((x) -> strings.add(printMany(x)));
        return "XI{[" + String.join(", ",strings) + "]}";
    }

    private String printYI(YIReader v) {
        List<ddlog_std_Option___bool__bit_8___string_Reader> val = v.v();
        ArrayList<String> strings = new ArrayList<String>(val.size());
        val.forEach((x) -> {
            if (x instanceof ddlog_std_Option___bool__bit_8___string_Reader.ddlog_std_Some) {
                strings.add("ddlog_std::Some{" + printTuple(((ddlog_std_Option___bool__bit_8___string_Reader.ddlog_std_Some)x).x()) + "}");
            } else {
                strings.add("ddlog_std::None{}");
            }
        });
        return "YI{[" + String.join(", ", strings) + "]}";
    }

    private String printStrings(List<String> v) {
        List<String> quoted = new ArrayList<String>();
        v.forEach((x) -> quoted.add("\"" + x + "\""));
        return quoted.toString();
    }

    private String printOptString(Object v) {
        if (v instanceof ddlog_std_Option__stringReader.ddlog_std_Some) {
            return "ddlog_std::Some{\"" + ((ddlog_std_Option__stringReader.ddlog_std_Some)v).x() + "\"}";
        } else {
            return "ddlog_std::None{}";
        }
    }

    private String printZI5(List<Tuple2__string__ManyReader> vs) {
        ArrayList<String> strings = new ArrayList<String>(vs.size());
        vs.forEach((t) -> strings.add("\"" + t.a0() + "\"=>" + printMany(t.a1())));
        return "{" + String.join(", ", strings) + "}";
    }

    private String printZI11(List<Tuple2__Many__stringReader> vs) {
        ArrayList<String> strings = new ArrayList<String>(vs.size());
        vs.forEach((t) -> strings.add(printMany(t.a0()) + "=>\"" + t.a1() + "\""));
        return "{" + String.join(", ", strings) + "}";
    }

    private String printZI12(Tuple4__string__bigint__ddlog_std_Vec_bigint____bit_16___Many_Reader v) {
        return "(\"" + v.a0() + "\", " + v.a1() +
                ", " + v.a2() + ", ("  + v.a3().a0() + ", " + printMany(v.a3().a1()) + "))";
    }

    private String printZI13(Generic___bool__bit_8___string___ManyReader v) {
        return "Generic{\"" + v.f0() +
            "\"," + printTuple(v.f1()) + "," + printMany(v.f2()) + "}";
    }

    // typedef Many = A{x: string}
    //              | B{b: bool}
    //              | D{t: tuple}
    private String printMany(ManyReader m) {
        if (m instanceof ManyReader.A) {
            return "A{\"" + ((ManyReader.A)m).x() + "\"}";
        } else if (m instanceof ManyReader.B) {
            return "B{" + ((ManyReader.B)m).b() + "}";
        } else if (m instanceof ManyReader.D) {
            return "D{" + printTuple(((ManyReader.D)m).t()) + "}";
        } else {
            throw new IllegalArgumentException("Invalid Many value " + m.toString());
        }
    }

    private String printCases(String relname, Cases__string__signed_32_Reader r) {
        if (r instanceof Cases__string__signed_32_Reader.First) {
            return relname + "{First{\"" + ((Cases__string__signed_32_Reader.First)r).a() + "\"}}";
        } else if (r instanceof Cases__string__signed_32_Reader.Second) {
            return relname + "{Second{" + ((Cases__string__signed_32_Reader.Second)r).b() + "}}";
        } else {
            throw new IllegalArgumentException("Invalid Cases value " + r.toString());
        }
    }

    private String printOr(String relname, Or__string__signed_32_Reader r) {
        if (r instanceof Or__string__signed_32_Reader.OrFirst) {
            return relname + "{OrFirst{FirstF{\"" + ((Or__string__signed_32_Reader.OrFirst)r).f().a() + "\"}}}";
        } else if (r instanceof Or__string__signed_32_Reader.OrSecond) {
            return relname + "{OrSecond{SecondS{" + ((Or__string__signed_32_Reader.OrSecond)r).s().a() + "}}}";
        } else {
            throw new IllegalArgumentException("Invalid Cases value " + r.toString());
        }
    }

    void onRecCommit(DDlogCommand command) throws IOException {
        rec_file.println(command.toString());
    }

    @SuppressWarnings("unchecked")
    void onFBCommit(DDlogCommand<Object> command) throws IOException {
        int relid = command.relid();
        switch (relid) {
            // output relation OBI(b: bool)
            case typesTestRelation.OBI: {
                BIReader v = (BIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " BI{" + v.b() + "}");
                break;
            }

            // output relation OCI(c: bit<32>)
            case typesTestRelation.OCI: {
                CIReader v = (CIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " CI{" + v.c() + "}");
                break;
            }

            // output relation ODI(d: signed<16>)
            case typesTestRelation.ODI: {
                DIReader v = (DIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " DI{" + v.d() + "}");
                break;
            }

            // output relation OEI(e: bigint)
            case typesTestRelation.OEI: {
                EIReader v = (EIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " EI{" + v.e() + "}");
                break;
            }

            // output relation OFI(s: string)
            case typesTestRelation.OFI: {
                FIReader v = (FIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " FI{\"" + v.s() + "\"}");
                break;
            }

            // output relation OGI(d: bit<64>)
            case typesTestRelation.OGI: {
                GIReader v = (GIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " GI{" + v.d() + "}");
                break;
            }

            // output relation OHI(d: bit<128>)
            case typesTestRelation.OHI: {
                HIReader v = (HIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " HI{" + v.d() + "}");
                break;
            }

            // output relation OII(d: bit<12>)
            case typesTestRelation.OII: {
                IIReader v = (IIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " II{" + v.d() + "}");
                break;
            }

            // output relation OJI(a: (bool, bit<8>, string))
            case typesTestRelation.OJI: {
                JIReader v = (JIReader)command.value();
                Tuple3__bool__bit_8___stringReader a = v.a();
                fb_file.println("From " + relid + " " + command.kind() + " JI{" + printTuple(a) + "}");
                break;
            }

            // output relation OKI(t: tuple)
            case typesTestRelation.OKI: {
                KIReader v = (KIReader)command.value();
                Tuple3__bool__bit_8___stringReader t = v.t();
                fb_file.println("From " + relid + " " + command.kind() + " KI{" + printTuple(t) + "}");
                break;
            }

            // output relation OLI[tuple]
            case typesTestRelation.OLI: {
                Tuple3__bool__bit_8___stringReader v = (Tuple3__bool__bit_8___stringReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + printTuple(v));
                break;
            }

            // output relation OL0I(a: bool, b: bit<8>, s: string)
            case typesTestRelation.OL0I: {
                L0IReader v = (L0IReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " L0I{" + v.a() + "," + v.b() + ",\"" + v.s() + "\"}");
                break;
            }

            // output relation OMI(v: Vec<bool>)
            case typesTestRelation.OMI: {
                MIReader v = (MIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " MI{" + v.v() + "}");
                break;
            }

            // output relation ONI(v: Vec<tuple>)
            case typesTestRelation.ONI: {
                NIReader v = (NIReader)command.value();
                List<Tuple3__bool__bit_8___stringReader> vs = v.v();
                ArrayList<String> strings = new ArrayList<String>(vs.size());
                vs.forEach((t) -> strings.add(printTuple(t)));
                fb_file.println("From " + relid + " " + command.kind() + " " + printNI((NIReader)command.value()));
                break;
            }

            // output relation OOI(v: Vec<Vec<bool>>)
            case typesTestRelation.OOI: {
                OIReader v = (OIReader)command.value();
                List<List<Boolean>> vs = v.v();
                fb_file.println("From " + relid + " " + command.kind() + " OI{" + vs + "}");
                break;
            }

            // output relation OPI1(s: Set<bit<8>>)
            case typesTestRelation.OPI1: {
                PI1Reader v = (PI1Reader)command.value();
                List<Integer> vs = v.s();
                fb_file.println("From " + relid + " " + command.kind() + " PI1{" + vs + "}");
                break;
            }

            // output relation OPI2(s: Set<bit<16>>)
            case typesTestRelation.OPI2: {
                PI2Reader v = (PI2Reader)command.value();
                List<Integer> vs = v.s();
                fb_file.println("From " + relid + " " + command.kind() + " PI2{" + vs + "}");
                break;
            }

            // output relation OPI3(s: Set<bit<32>>)
            case typesTestRelation.OPI3: {
                PI3Reader v = (PI3Reader)command.value();
                List<Long> vs = v.s();
                fb_file.println("From " + relid + " " + command.kind() + " PI3{" + vs + "}");
                break;
            }

            // output relation OPI4(s: Set<bit<64>>)
            case typesTestRelation.OPI4: {
                PI4Reader v = (PI4Reader)command.value();
                List<Long> vs = v.s();
                fb_file.println("From " + relid + " " + command.kind() + " PI4{" + vs + "}");
                break;
            }

            // output relation OPI5(s: Set<bit<128>>)
            case typesTestRelation.OPI5: {
                PI5Reader v = (PI5Reader)command.value();
                List<BigInteger> vs = v.s();
                fb_file.println("From " + relid + " " + command.kind() + " PI5{" + vs + "}");
                break;
            }

            // output relation OQI(m: Map<bit<32>, string>)
            case typesTestRelation.OQI: {
                QIReader v = (QIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + printQI(v));
                break;
            }

            // output relation ORI(m: Ref<bit<32>>)
            case typesTestRelation.ORI: {
                RIReader v = (RIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " RI{" + v.m() + "}");
                break;
            }

            // output relation OSI(m: C)
            case typesTestRelation.OSI: {
                SIReader v = (SIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " SI{C{\"" + v.m().x() + "\"}}");
                break;
            }

            // output relation OTI(m: Option<bit<32>>)
            case typesTestRelation.OTI: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printTI((TIReader)command.value()));
                break;
            }

            // output relation OUI[Many]
            case typesTestRelation.OUI: {
                ManyReader m = (ManyReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + printMany(m));
                break;
            }

            //output relation OVI(a: bool, b: Many)
            case typesTestRelation.OVI: {
                VIReader v = (VIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " VI{" + v.a() + "," + printMany(v.b()) + "}");
                break;
            }

            // output relation OWI(m: Option<Many>)
            case typesTestRelation.OWI: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printWI((WIReader)command.value()));
                break;
            }

            //output relation OXI(m: Vec<Many>)
            case typesTestRelation.OXI: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printXI((XIReader)command.value()));
                break;
            }

            //typedef VOT = Vec<Option<tuple>>
            // output relation OYI(v: VOT)
            case typesTestRelation.OYI: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printYI((YIReader)command.value()));
                break;
            }
            // output relation OZI0[string]
            case typesTestRelation.OZI0: {
                String v = (String)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " \"" + v + "\"");
                break;
            }
            // output relation OZI1[bool]
            case typesTestRelation.OZI1: {
                Boolean v = (Boolean)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + v);
                break;
            }
            // output relation OZI2[bit<32>]
            case typesTestRelation.OZI2: {
                Long v = (Long)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + v);
                break;
            }
            // output relation OZI3[Many]
            case typesTestRelation.OZI3: {
                ManyReader v = (ManyReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + printMany(v));
                break;
            }
            // output relation OZI4[Vec<string>]
            case typesTestRelation.OZI4: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printStrings((List<String>)command.value()));
                break;
            }
            // output relation OZI5[Map<string, Many>]
            case typesTestRelation.OZI5: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printZI5((List<Tuple2__string__ManyReader>)command.value()));
                break;
            }
            // output relation OZI6[Option<string>]
            case typesTestRelation.OZI6: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printOptString(command.value()));
                break;
            }
            // output relation OZI7[Ref<string>]
            case typesTestRelation.OZI7: {
                String v = (String)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " \"" + v + "\"");
                break;
            }
            // output relation OZI8[Ref<bit<25>>]
            case typesTestRelation.OZI8: {
                Long v = (Long)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + v);
                break;
            }
            // output relation OZI9[Ref<Ref<bit<25>>>]
            case typesTestRelation.OZI9: {
                Long v = (Long)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + v);
                break;
            }
            // output relation OZI10[Ref<IString>]
            case typesTestRelation.OZI10: {
                String v = (String)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " \"" + v + "\"");
                break;
            }
            // output relation OZI11[Map<Many, string>]
            case typesTestRelation.OZI11: {
                fb_file.println("From " + relid + " " + command.kind() + " " + printZI11((List<Tuple2__Many__stringReader>)command.value()));
                break;
            }
            // output relation OZI12[(string, bigint, Vec<bigint>, (bit<16>, Many))]
            case typesTestRelation.OZI12: {
                fb_file.println("From " + relid + " " + command.kind() + " " +
                        printZI12((Tuple4__string__bigint__ddlog_std_Vec_bigint____bit_16___Many_Reader)command.value()));
                break;
            }
            // output relation OZI13[Generic<Ref<tuple>, Many>]
            case typesTestRelation.OZI13: {
                fb_file.println("From " + relid + " " + command.kind() + " " +
                        printZI13((Generic___bool__bit_8___string___ManyReader)command.value()));
                break;
            }
            // output relation OZI(d: bit<256>)
            case typesTestRelation.OZI: {
                ZIReader z = (ZIReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " ZI{" + z.d() + "}");
                break;
            }
            case typesTestRelation.OZI14: {
                ZI14Reader r = (ZI14Reader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + printCases("ZI14", r.c()));
                break;
            }
            case typesTestRelation.OZI15: {
                ZI15Reader r = (ZI15Reader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + printOr("ZI15", r.c()));
                break;
            }
            case typesTestRelation.module_OZI16: {
                module_ZI16Reader r = (module_ZI16Reader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " module::ZI16{\"" + r.x() + "\"}");
                break;
            }
            case typesTestRelation.module_OZI17: {
                String r = (String)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " \"" + r + "\"");
                break;
            }
            case typesTestRelation.module_OZI18: {
                module_ZI18Reader b = (module_ZI18Reader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " module::ZI18{" + printMTuple(b.t()) + "}");
                break;
            }
            case typesTestRelation.module_OZI19: {
                Tuple2__bit_32___stringReader b = (Tuple2__bit_32___stringReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " " + printMTuple(b));
                break;
            }
            case typesTestRelation.OZI20: {
                ZI20Reader b = (ZI20Reader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " ZI20{" + printMTuple(b.t()) + "}");
                break;
            }
            case typesTestRelation.OZI21: {
                ZI21Reader m = (ZI21Reader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " ZI21{" + m.m() + "}");
                break;
            }
            case typesTestRelation.OZJ: {
                ZJReader m = (ZJReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " ZJ{" + m.d() + "}");
                break;
            }
            case typesTestRelation.OZK: {
                ZKReader m = (ZKReader)command.value();
                fb_file.println("From " + relid + " " + command.kind() + " ZK{" + m.f() + "}");
                break;
            }
            default:
                fb_file.println("Unknown output relation " + relid);
                //throw new IllegalArgumentException("Unknown relation id " + relid);
        }

    }

    void update() throws DDlogException {
        typesTestUpdateBuilder builder = new typesTestUpdateBuilder();
        builder.insert_BI(true);
        builder.insert_CI((byte)8);
        builder.insert_DI((short)-5);
        builder.insert_DI((short)-1);
        builder.insert_DI((short)-2);
        builder.insert_DI((short)-3);
        builder.insert_DI((short)5);
        builder.insert_DI((short)1000);
        builder.insert_DI((short)Short.MAX_VALUE);
        builder.insert_DI((short)Short.MIN_VALUE);
        builder.insert_EI(BigInteger.ZERO.subtract(BigInteger.ONE));
        builder.insert_FI("string");
        builder.insert_GI((long)100);
        builder.insert_HI(new BigInteger("0ABACABA0ABACABA", 16));
        builder.insert_II((short)7);
        {
            Tuple3__bool__bit_8___stringWriter ji = builder.create_Tuple3__bool__bit_8___string(true, (byte)10, "string");
            builder.insert_JI(ji);
        }
        {
            Tuple3__bool__bit_8___stringWriter ki = builder.create_Tuple3__bool__bit_8___string(false, (byte)9, "text");
            builder.insert_KI(ki);
        }
        builder.insert_LI(true, (byte)-1, "something");
        builder.insert_L0I(true, (byte)-1, "or not");
        builder.insert_L0I(false, (byte)-2, "else");
        builder.insert_or_update_L0I(false, (byte)-2, "altogether");
        {
            Boolean[] v = new Boolean[] {true, false, true};
            builder.insert_MI(Arrays.asList(v));
        }
        {
            ArrayList<Tuple3__bool__bit_8___stringWriter> vec = new ArrayList<Tuple3__bool__bit_8___stringWriter>(2);
            vec.add(builder.create_Tuple3__bool__bit_8___string(true, (byte)-1, "check"));
            vec.add(builder.create_Tuple3__bool__bit_8___string(false, (byte)1, "fails"));
            builder.insert_NI(vec);
        }
        {
            List<Boolean> l1 = Arrays.asList(new Boolean[] {false, false});
            List<Boolean> l2 = Arrays.asList(new Boolean[] {true, true});
            List<List<Boolean>> nest = new ArrayList<List<Boolean>>(2);
            nest.add(l1);
            nest.add(l2);
            builder.insert_OI(nest);
        }
        {
            List<Byte> pi = Arrays.asList(new Byte[]{ -2, 3, 2, 3 });
            builder.insert_PI1(pi);
        }
        {
            List<Short> pi = Arrays.asList(new Short[]{ 10000, 3, -2, 3 });
            builder.insert_PI2(pi);
        }
        {
            List<Integer> pi = Arrays.asList(new Integer[]{ 0xffffffff, 3, -2, 3 });
            builder.insert_PI3(pi);
        }
        {
            List<Long> pi = Arrays.asList(new Long[]{ 2L, 3L, 2L, 3L });
            builder.insert_PI4(pi);
        }
        {
            List<BigInteger> pi = Arrays.asList(new BigInteger[]{
                BigInteger.valueOf(0xffffffffffffffL),
                BigInteger.valueOf(3),
                BigInteger.valueOf(2),
                BigInteger.valueOf(3)
            });
            builder.insert_PI5(pi);
        }
        {
            ArrayList<Tuple2__bit_32___stringWriter> map = new ArrayList<Tuple2__bit_32___stringWriter>();
            map.add(builder.create_Tuple2__bit_32___string(2, "here"));
            map.add(builder.create_Tuple2__bit_32___string(3, "there"));
            builder.insert_QI(map);
        }
        builder.insert_RI(2);
        {
            CWriter c = builder.create_C("s");
            builder.insert_SI(c);
        }
        {
            ddlog_std_Option__bit_32_Writer b = builder.create_ddlog_std_Some__bit_32_(10);
            builder.insert_TI(b);
            ddlog_std_Option__bit_32_Writer b1 = builder.create_ddlog_std_None__bit_32_();
            builder.insert_TI(b1);
        }
        builder.insert_UI_A("a");
        builder.insert_UI_B(false);
        builder.insert_UI_D(builder.create_Tuple3__bool__bit_8___string(false, (byte)2, "zz"));
        {
            ManyWriter a = builder.create_A("aa");
            ManyWriter b = builder.create_B(false);
            ManyWriter d = builder.create_D(builder.create_Tuple3__bool__bit_8___string(false, (byte)2, "string"));
            builder.insert_VI(false, a);
            builder.insert_VI(true, b);
            builder.insert_VI(false, d);
        }
        {
            ddlog_std_Option__ManyWriter om0 = builder.create_ddlog_std_None__Many();
            builder.insert_WI(om0);
            ddlog_std_Option__ManyWriter om1 = builder.create_ddlog_std_Some__Many(builder.create_B(true));
            builder.insert_WI(om1);
        }
        {
            ManyWriter[] m = {
                builder.create_A("aa"),
                builder.create_B(false),
                builder.create_D(builder.create_Tuple3__bool__bit_8___string(false, (byte)2, "string"))
            };
            builder.insert_XI(Arrays.asList(m));
        }
        {
            ddlog_std_Option___bool__bit_8___string_Writer[] v = {
                builder.create_ddlog_std_Some___bool__bit_8___string_(
                    builder.create_Tuple3__bool__bit_8___string(false, (byte)-1, "")),
                builder.create_ddlog_std_Some___bool__bit_8___string_(
                    builder.create_Tuple3__bool__bit_8___string(true, (byte)-2, "!")),
                builder.create_ddlog_std_None___bool__bit_8___string_()
            };
            builder.insert_YI(Arrays.asList(v));
        }
        builder.insert_ZI0("Hello, world!");
        builder.insert_ZI0("Привіт!");
        builder.insert_ZI1(true);
        builder.insert_ZI1(false);
        builder.insert_ZI2((long)0);
        builder.insert_ZI2((long)1000);
        builder.insert_ZI3_A("It's all Greek to me:  Α α, Β β, Γ γ, Δ δ, Ε ε, Ζ ζ, Η η, Θ θ, Ι ι, Κ κ, Λ λ, Μ μ, Ν ν, Ξ ξ, Ο ο, Π π, Ρ ρ, Σ σ/ς, Τ τ, Υ υ, Φ φ, Χ χ, Ψ ψ, Ω ω.");
        {
            ArrayList<String> strings = new ArrayList<String>();
            strings.add("Foo\n");
            strings.add("\tbar");
            builder.insert_ZI4(strings);
        }
        {
            ArrayList<Tuple2__string__ManyWriter> map = new ArrayList<Tuple2__string__ManyWriter>();
            map.add(builder.create_Tuple2__string__Many("key1", builder.create_B(false)));
            map.add(builder.create_Tuple2__string__Many("key2", builder.create_A("val2")));
            builder.insert_ZI5(map);
        }
        builder.insert_ZI6_ddlog_std_Some("ZI6");
        builder.insert_ZI6_ddlog_std_None();
        builder.insert_ZI7("♛");
        builder.insert_ZI7("ZI7");
        builder.insert_ZI8(100);
        builder.insert_ZI9(100);
        builder.insert_ZI10("Ref<IString>");
        {
            ArrayList<Tuple2__Many__stringWriter> map = new ArrayList<Tuple2__Many__stringWriter>();
            //map.put(builder.create_B(false), "v1");
            // Cannot add more than one record, since the map is printed in
            // non-deterministic order, so the diff fails.
            map.add(builder.create_Tuple2__Many__string(builder.create_A("val2"), "v2"));
            builder.insert_ZI11(map);
        }
        {
            ArrayList<BigInteger> ints = new ArrayList<BigInteger>();
            ints.add(BigInteger.valueOf(0));
            ints.add(BigInteger.valueOf(0));
            ints.add(BigInteger.valueOf(1));
            builder.insert_ZI12(
                    "ZI12",
                    BigInteger.valueOf(1000000),
                    ints,
                    builder.create_Tuple2__bit_16___Many(0x10,
                        builder.create_D(builder.create_Tuple3__bool__bit_8___string(false, (byte)2, "string"))));
        }
        {
            ArrayList<BigInteger> ints = new ArrayList<BigInteger>();
            ints.add(BigInteger.valueOf(0));
            ints.add(BigInteger.valueOf(0));
            ints.add(BigInteger.valueOf(1));
            builder.insert_ZI13("ZI13", builder.create_Tuple3__bool__bit_8___string(false, (byte)2, "string"),
                    builder.create_A("ZI13"));
        }
        {
            BigInteger b = new BigInteger("01234566788901239813761283");
            builder.insert_ZI(b);
        }
        {
            Cases__string__signed_32_Writer w1 = builder.create_First__string__signed_32_("string");
            Cases__string__signed_32_Writer w2 = builder.create_Second__string__signed_32_(5);
            builder.insert_ZI14(w1);
            builder.insert_ZI14(w2);
        }
        {
            F__stringWriter f = builder.create_F__string("Or_string");
            Or__string__signed_32_Writer w1 = builder.create_OrFirst__string__signed_32_(f);
            S__signed_32_Writer s = builder.create_S__signed_32_(22);
            Or__string__signed_32_Writer w2 = builder.create_OrSecond__string__signed_32_(s);
            builder.insert_ZI15(w1);
            builder.insert_ZI15(w2);
        }
        {
            builder.insert_module_ZI16("zi16");
        }
        {
            builder.insert_module_ZI17("zi17");
        }
        {
            Tuple2__bit_32___stringWriter b = builder.create_Tuple2__bit_32___string(-1, "ZZZ");
            builder.insert_module_ZI18(b);
        }
        {
            builder.insert_module_ZI19(-3, "zi19");
        }
        {
            Tuple2__bit_32___stringWriter b = builder.create_Tuple2__bit_32___string(-2, "YYY");
            builder.insert_ZI20(b);
        }
        builder.insert_ZI21(13);
        builder.insert_ZJ(5.0);
        builder.insert_ZK(5.0f);
        builder.applyUpdates(this.api);
        try {
            builder.applyUpdates(this.api);
            assert false: "Reusing UpdateBuilder should throw an exception.";
        } catch (IllegalStateException e) {}

        // Test delete.  This fails if the element is not present in the collection.
        builder = new typesTestUpdateBuilder();
        builder.delete_by_key_L0I(true);
        builder.applyUpdates(this.api);
    }

    void clear() throws DDlogException {
        this.api.clearRelation(typesTestRelation.BI);
        this.api.clearRelation(typesTestRelation.CI);
        this.api.clearRelation(typesTestRelation.DI);
        this.api.clearRelation(typesTestRelation.EI);
        this.api.clearRelation(typesTestRelation.FI);
        this.api.clearRelation(typesTestRelation.GI);
        this.api.clearRelation(typesTestRelation.HI);
        this.api.clearRelation(typesTestRelation.II);
        this.api.clearRelation(typesTestRelation.JI);
        this.api.clearRelation(typesTestRelation.KI);
        this.api.clearRelation(typesTestRelation.LI);
        this.api.clearRelation(typesTestRelation.L0I);
        this.api.clearRelation(typesTestRelation.MI);
        this.api.clearRelation(typesTestRelation.NI);
        this.api.clearRelation(typesTestRelation.OI);
        this.api.clearRelation(typesTestRelation.PI1);
        this.api.clearRelation(typesTestRelation.PI2);
        this.api.clearRelation(typesTestRelation.PI3);
        this.api.clearRelation(typesTestRelation.PI4);
        this.api.clearRelation(typesTestRelation.PI5);
        this.api.clearRelation(typesTestRelation.QI);
        this.api.clearRelation(typesTestRelation.RI);
        this.api.clearRelation(typesTestRelation.SI);
        this.api.clearRelation(typesTestRelation.TI);
        this.api.clearRelation(typesTestRelation.UI);
        this.api.clearRelation(typesTestRelation.VI);
        this.api.clearRelation(typesTestRelation.WI);
        this.api.clearRelation(typesTestRelation.XI);
        this.api.clearRelation(typesTestRelation.YI);
        this.api.clearRelation(typesTestRelation.ZI0);
        this.api.clearRelation(typesTestRelation.ZI1);
        this.api.clearRelation(typesTestRelation.ZI2);
        this.api.clearRelation(typesTestRelation.ZI3);
        this.api.clearRelation(typesTestRelation.ZI4);
        this.api.clearRelation(typesTestRelation.ZI5);
        this.api.clearRelation(typesTestRelation.ZI6);
        this.api.clearRelation(typesTestRelation.ZI7);
        this.api.clearRelation(typesTestRelation.ZI8);
        this.api.clearRelation(typesTestRelation.ZI9);
        this.api.clearRelation(typesTestRelation.ZI10);
        this.api.clearRelation(typesTestRelation.ZI11);
        this.api.clearRelation(typesTestRelation.ZI12);
        this.api.clearRelation(typesTestRelation.ZI13);
        this.api.clearRelation(typesTestRelation.ZI);
        this.api.clearRelation(typesTestRelation.ZI14);
        this.api.clearRelation(typesTestRelation.ZI15);
        this.api.clearRelation(typesTestRelation.module_ZI16);
        this.api.clearRelation(typesTestRelation.module_ZI17);
        this.api.clearRelation(typesTestRelation.module_ZI18);
        this.api.clearRelation(typesTestRelation.module_ZI19);
        this.api.clearRelation(typesTestRelation.ZI20);
        this.api.clearRelation(typesTestRelation.ZI21);
        this.api.clearRelation(typesTestRelation.ZJ);
        this.api.clearRelation(typesTestRelation.ZK);
    }

    void run() throws IOException, DDlogException {
        /* Create and commit commands using record-based API.
         */
        // TODO: expand this portion of the test to test the complete record API
        // by populating all test relations.
        this.rec_file = new PrintStream("rec_dynamic.dump");
        this.api.transactionStart();
        //input relation ZK(f: float)
        DDlogRecord[] f = {new DDlogRecord(0.5F)};
        DDlogRecord zk = DDlogRecord.makeStruct("ZK", f);
        DDlogRecCommand c1 = new DDlogRecCommand(DDlogCommand.Kind.Insert, this.api.getTableId("ZK"), zk);
        //input relation ZJ(d: double)
        DDlogRecord[] d = {new DDlogRecord(1.5E-2D)};
        DDlogRecord zj = DDlogRecord.makeStruct("ZJ", d);
        DDlogRecCommand c2 = new DDlogRecCommand(DDlogCommand.Kind.Insert, this.api.getTableId("ZJ"), zj);
        DDlogRecCommand[] cmds = {c1, c2};
        this.api.applyUpdates(cmds);

        this.api.transactionCommitDumpChanges(r -> {
            try {
                this.onRecCommit(r);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        });
        this.rec_file.close();
        this.rec_file = new PrintStream("rec.dump");

        /* Create commands using flatbuf-based API; commit using DDlogRecord-based API. */
        this.api.transactionStart();
        this.update();
        this.api.transactionCommitDumpChanges(r -> {
            try {
                this.onRecCommit(r);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        });
        this.rec_file.close();

        /* Clear all input relations */
        this.api.transactionStart();
        this.clear();
        this.api.transactionCommit();

        /* FlatBuffers-based coommit */
        this.api.transactionStart();
        this.update();
        typesTestUpdateParser.transactionCommitDumpChanges(this.api, r -> {
            try {
                this.onFBCommit(r);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        });

        /* Test queries */
        query_file.println("Query CI_by_c[0]:");
        typesTestQuery.queryCI_by_c(this.api, 0, v -> {
            query_file.println("CI{" + v.c() + "}");
        });

        query_file.println("Query CI_by_c[8]:");
        typesTestQuery.queryCI_by_c(this.api, 8, v -> {
            query_file.println("CI{" + v.c() + "}");
        });

        query_file.println("Query DI_by_d[0]:");
        typesTestQuery.queryDI_by_d(this.api, (short)0, v -> {
            query_file.println("DI{" + v.d() + "}");
        });
        query_file.println("Query DI_by_d[1000]:");
        typesTestQuery.queryDI_by_d(this.api, (short)1000, v -> {
            query_file.println("DI{" + v.d() + "}");
        });
        query_file.println("Query DI_by_none[]:");
        typesTestQuery.queryDI_by_none(this.api, v -> {
            query_file.println("DI{" + v.d() + "}");
        });

        query_file.println("Query EI_by_e[-1]:");
        typesTestQuery.queryEI_by_e(this.api, BigInteger.ZERO.subtract(BigInteger.ONE), v -> {
            query_file.println("EI{" + v.e() + "}");
        });
        query_file.println("Query EO_by_e[-1]:");
        typesTestQuery.queryEO_by_e(this.api, BigInteger.ZERO.subtract(BigInteger.ONE), v -> {
            query_file.println("EO{" + v.e() + "}");
        });

        query_file.println("Query FI_by_s[\"α,\"]:");
        typesTestQuery.queryFI_by_s(this.api, "α", v -> {
            query_file.println("FI{\"" + v.s() + "\"}");
        });
        query_file.println("Query FI_by_s[\"string\"]:");
        typesTestQuery.queryFI_by_s(this.api, "string", v -> {
            query_file.println("FI{\"" + v.s() + "\"}");
        });

        query_file.println("Query GI_by_d[-100]:");
        typesTestQuery.queryGI_by_d(this.api, (long)-100, v -> {
            query_file.println("GI{" + v.d() + "}");
        });
        query_file.println("Query GI_by_d[100]:");
        typesTestQuery.queryGI_by_d(this.api, (long)100, v -> {
            query_file.println("GI{" + v.d() + "}");
        });

        query_file.println("Query HI_by_d[0ABACABA0ABACABA]:");
        typesTestQuery.queryHI_by_d(this.api, new BigInteger("0ABACABA0ABACABA", 16), v -> {
            query_file.println("HI{" + v.d() + "}");
        });

        query_file.println("Query II_by_d[7]:");
        typesTestQuery.queryII_by_d(this.api, 7, v -> {
            query_file.println("II{" + v.d() + "}");
        });

        query_file.println("Query JI_by_0[true]:");
        typesTestQuery.queryJI_by_0(this.api, true, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_1[10]:");
        typesTestQuery.queryJI_by_1(this.api, 10, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_2[\"string\"]:");
        typesTestQuery.queryJI_by_2(this.api, "string", v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_01[true, 10]:");
        typesTestQuery.queryJI_by_01(this.api, true, 10, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_01[false, 10]:");
        typesTestQuery.queryJI_by_01(this.api, false, 10, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_02[true, \"string\"]:");
        typesTestQuery.queryJI_by_02(this.api, true, "string", v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_12[10, \"string\"]:");
        typesTestQuery.queryJI_by_12(this.api, 10, "string", v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_012[true, 10, \"string\"]:");
        typesTestQuery.queryJI_by_012(this.api, true, 10, "string", v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Query JI_by_all[true, 10, \"string\"]:");
        typesTestQuery.queryJI_by_all(this.api,
                bldr -> {
                    return bldr.create_Tuple3__bool__bit_8___string(true, (byte)10, "string");
                },
                v -> {
                    query_file.println("JI{" + printTuple(v.a()) + "}");
                });
        query_file.println("Query JI_by_self[true, 10, \"string\"]:");
        typesTestQuery.queryJI_by_self(this.api,
                bldr -> {
                    return bldr.create_JI(bldr.create_Tuple3__bool__bit_8___string(true, (byte)10, "string"));
                },
                v -> {
                    query_file.println("JI{" + printTuple(v.a()) + "}");
                });
        query_file.println("Query JI_by_10[10, true]:");
        typesTestQuery.queryJI_by_10(this.api, 10, true, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });

        query_file.println("Query KI_by_01[false, 9]:");
        typesTestQuery.queryKI_by_01(this.api, false, 9, v -> {
            query_file.println("KI{" + printTuple(v.t()) + "}");
        });
        query_file.println("Query KI_by_all[false, 9, \"text\"]:");
        typesTestQuery.queryKI_by_all(this.api,
                bldr -> {
                    return bldr.create_Tuple3__bool__bit_8___string(false, (byte)9, "text");
                },
                v -> {
                    query_file.println("KI{" + printTuple(v.t()) + "}");
                });

        query_file.println("Query LI_by_01[true, -1]:");
        typesTestQuery.queryLI_by_01(this.api, true, -1, v -> {
            query_file.println(printTuple((Tuple3__bool__bit_8___stringReader)v));

        });
        query_file.println("Query LI_by_all[true, -1, \"something\"]:");
        typesTestQuery.queryLI_by_all(this.api,
                bldr -> {
                    return bldr.create_Tuple3__bool__bit_8___string(true, (byte)-1, "something");
                },
                v -> {
                    query_file.println(printTuple((Tuple3__bool__bit_8___stringReader)v));
                });

        query_file.println("Query L0I[true]:");
        typesTestQuery.queryL0I_by_a(this.api, true, v -> {
            query_file.println("L0I{" + v.a() + "," + v.b() + ",\"" + v.s() + "\"}");
        });
        query_file.println("Query L0I[false]:");
        typesTestQuery.queryL0I_by_a(this.api, false, v -> {
            query_file.println("L0I{" + v.a() + "," + v.b() + ",\"" + v.s() + "\"}");
        });

        query_file.println("Query MI_by_v[true, false, true]:");
        typesTestQuery.queryMI_by_v(this.api, Arrays.asList(new Boolean[] {true, false, true}), v -> {
            query_file.println("MI{" + v.v() + "}");
        });

        query_file.println("Query NI_by_v[(true,-1,\"check\"), (false,1,\"fails\")]:");
        typesTestQuery.queryNI_by_v(this.api,
                bldr -> {
                    ArrayList<Tuple3__bool__bit_8___stringWriter> vec = new ArrayList<Tuple3__bool__bit_8___stringWriter>(2);
                    vec.add(bldr.create_Tuple3__bool__bit_8___string(true, (byte)-1, "check"));
                    vec.add(bldr.create_Tuple3__bool__bit_8___string(false, (byte)1, "fails"));
                    return vec;
                },
                v -> {
                    query_file.println(printNI(v));
                });

        query_file.println("Query OI_by_v[[false,false],[true, true]]:");
        List<Boolean> l1 = Arrays.asList(new Boolean[] {false, false});
        List<Boolean> l2 = Arrays.asList(new Boolean[] {true, true});
        List<List<Boolean>> nest = new ArrayList<List<Boolean>>(2);
        nest.add(l1);
        nest.add(l2);
        typesTestQuery.queryOI_by_v(this.api, nest,
                v -> {
                    query_file.println("OI{" + v.v() + "}");
                });

        query_file.println("Query PI1_by_s[-2, 3, 2, 3]:");
        typesTestQuery.queryPI1_by_s(this.api, Arrays.asList(new Byte[]{ -2, 3, 2, 3 }), v -> {
            query_file.println("PI1{" + v.s() + "}");
        });

        query_file.println("Query PI2_by_s[10000, 3, -2, 3]:");
        typesTestQuery.queryPI2_by_s(this.api, Arrays.asList(new Short[]{ 10000, 3, -2, 3 }), v -> {
            query_file.println("PI2{" + v.s() + "}");
        });

        query_file.println("Query PI3_by_s[0xffffffff, 3, -2, 3]:");
        typesTestQuery.queryPI3_by_s(this.api, Arrays.asList(new Integer[]{ 0xffffffff, 3, -2, 3 }), v -> {
            query_file.println("PI3{" + v.s() + "}");
        });

        query_file.println("Query PI4_by_s[2, 3, 2, 3]:");
        typesTestQuery.queryPI4_by_s(this.api, Arrays.asList(new Long[]{ 2L, 3L, 2L, 3L }), v -> {
            query_file.println("PI4{" + v.s() + "}");
        });
        query_file.println("Query PI4_by_none[]:");
        typesTestQuery.queryPI4_by_none(this.api, v -> {
            query_file.println("PI4{" + v.s() + "}");
        });
        query_file.println("Query PI4_by_self[2, 3, 2, 3]:");
        typesTestQuery.queryPI4_by_self(this.api,
                bldr -> {
                    return bldr.create_PI4(Arrays.asList(new Long[]{ 2L, 3L, 2L, 3L }));
                },
                v -> {
                    query_file.println("PI4{" + v.s() + "}");
                });

        query_file.println("Query PI5_by_s[0xffffffffffffff, 3, 2, 3]:");
        List<BigInteger> pi = Arrays.asList(new BigInteger[]{
            BigInteger.valueOf(0xffffffffffffffL),
            BigInteger.valueOf(3),
            BigInteger.valueOf(2),
            BigInteger.valueOf(3)
        });
        typesTestQuery.queryPI5_by_s(this.api, pi, v -> {
            query_file.println("PI5{" + v.s() + "}");
        });

        query_file.println("Query QI_by_m[(2=>\"here\", 3=>\"there\"]:");
        {
            typesTestQuery.queryQI_by_m(this.api,
                bldr -> {
                    ArrayList<Tuple2__bit_32___stringWriter> map = new ArrayList<Tuple2__bit_32___stringWriter>();
                    map.add(bldr.create_Tuple2__bit_32___string(Long.valueOf(2), "here"));
                    map.add(bldr.create_Tuple2__bit_32___string(Long.valueOf(3), "there"));
                    return map;
                },
                v -> {
                    query_file.println(printQI(v));
                });
        }

        query_file.println("Query RI_by_refm[2]:");
        typesTestQuery.queryRI_by_refm(this.api, 2, v -> {
            query_file.println("RI{" + v.m() + "}");
        });
        query_file.println("Query RI_by_m[2]:");
        typesTestQuery.queryRI_by_m(this.api, 2, v -> {
            query_file.println("RI{" + v.m() + "}");
        });

        query_file.println("Query SI_by_m[\"s\"]:");
        typesTestQuery.querySI_by_m(this.api,
                bldr -> {
                    return bldr.create_C("s");
                },
                v -> {
                    query_file.println("SI{C{\"" + v.m().x() + "\"}}");
                });
        query_file.println("Query SI_by_x[\"s\"]:");
        typesTestQuery.querySI_by_x(this.api, "s",
                v -> {
                    query_file.println("SI{C{\"" + v.m().x() + "\"}}");
                });

        query_file.println("Query TI_by_m[10]:");
        typesTestQuery.queryTI_by_m(this.api,
                bldr -> {
                    return bldr.create_ddlog_std_Some__bit_32_(10);
                },
                v -> {
                    query_file.println(printTI(v));
                });
        query_file.println("Query TI_by_some[10]:");
        typesTestQuery.queryTI_by_some(this.api, 10, v -> {
                    query_file.println(printTI(v));
                });
        query_file.println("Query TI_by_none[]:");
        typesTestQuery.queryTI_by_none(this.api, v -> {
                    query_file.println(printTI(v));
                });

        query_file.println("Query UI_by_x[\"a\"]:");
        typesTestQuery.queryUI_by_x(this.api, "a",
                v -> { query_file.println(printMany(v)); });
        query_file.println("Query UI_by_b[false]:");
        typesTestQuery.queryUI_by_b(this.api, false,
                v -> { query_file.println(printMany(v)); });
        query_file.println("Query UI_by_t[(false, 2, \"zz\")]:");
        typesTestQuery.queryUI_by_t(this.api,
                bldr -> {
                    return bldr.create_Tuple3__bool__bit_8___string(false, (byte)2, "zz");
                },
                v -> { query_file.println(printMany(v)); });
        query_file.println("Query UI_by_t1[2]:");
        typesTestQuery.queryUI_by_t1(this.api, 2,
                v -> { query_file.println(printMany(v)); });

        query_file.println("Query VI_by_a[false]:");
        typesTestQuery.queryVI_by_a(this.api, false,
                v -> {
                    query_file.println("VI{" + v.a() + "," + printMany(v.b()) + "}");
                });
        query_file.println("Query VI_by_t1[2]:");
        typesTestQuery.queryVI_by_t1(this.api, 2,
                v -> {
                    query_file.println("VI{" + v.a() + "," + printMany(v.b()) + "}");
                });

        query_file.println("Query WI_by_t2[\"foo\"]:");
        typesTestQuery.queryWI_by_t2(this.api, "foo",
                v -> { query_file.println(printWI(v)); });
        query_file.println("Query WI_by_t[(false, 2, \"string\")]:");
        typesTestQuery.queryWI_by_t(this.api,
                bldr -> {
                    return bldr.create_Tuple3__bool__bit_8___string(false, (byte)2, "string");
                },
                v -> { query_file.println(printWI(v)); });

        query_file.println("Query XI_by_m[A{\"aa\"}, B{false}, D{(false,2,\"string\")}]:");
        typesTestQuery.queryXI_by_m(this.api,
                bldr -> {
                    ManyWriter[] m = {
                        bldr.create_A("aa"),
                        bldr.create_B(false),
                        bldr.create_D(bldr.create_Tuple3__bool__bit_8___string(false, (byte)2, "string"))
                    };
                    return Arrays.asList(m);
                },
                v -> { query_file.println(printXI(v)); });

        query_file.println("Query YI_by_v[...]:");
        typesTestQuery.queryYI_by_v(this.api,
                bldr -> {
                    ddlog_std_Option___bool__bit_8___string_Writer[] v = {
                        bldr.create_ddlog_std_Some___bool__bit_8___string_(
                                bldr.create_Tuple3__bool__bit_8___string(false, (byte)-1, "")),
                        bldr.create_ddlog_std_Some___bool__bit_8___string_(
                                bldr.create_Tuple3__bool__bit_8___string(true, (byte)-2, "!")),
                        bldr.create_ddlog_std_None___bool__bit_8___string_()
                    };
                    return Arrays.asList(v);
                },
                v -> { query_file.println(printYI(v)); });
        query_file.println("Query YI_by_none[]:");
        typesTestQuery.queryYI_by_none(this.api,
                v -> { query_file.println(printYI(v)); });
        query_file.println("Query YI_by_self[...]:");
        typesTestQuery.queryYI_by_self(this.api,
                bldr -> {
                    ddlog_std_Option___bool__bit_8___string_Writer[] v = {
                        bldr.create_ddlog_std_Some___bool__bit_8___string_(
                                bldr.create_Tuple3__bool__bit_8___string(false, (byte)-1, "")),
                        bldr.create_ddlog_std_Some___bool__bit_8___string_(
                                bldr.create_Tuple3__bool__bit_8___string(true, (byte)-2, "!")),
                        bldr.create_ddlog_std_None___bool__bit_8___string_()
                    };
                    return bldr.create_YI(Arrays.asList(v));
                },
                v -> { query_file.println(printYI(v)); });

        query_file.println("Query ZI_by_d[0]:");
        typesTestQuery.queryZI_by_d(this.api, BigInteger.valueOf(0),
                v -> { query_file.println("HI{" + v.d() + "}"); });

        query_file.println("Query ZI0_by_self[\"Привіт!\"]:");
        typesTestQuery.queryZI0_by_self(this.api, "Привіт!",
                v -> { query_file.println("\"" + v + "\""); });

        query_file.println("Query ZI1_by_self[false]:");
        typesTestQuery.queryZI1_by_self(this.api, false,
                v -> { query_file.println(v); });
        query_file.println("Query ZI1_by_true[]:");
        typesTestQuery.queryZI1_by_true(this.api,
                v -> { query_file.println(v); });

        query_file.println("Query ZI2_by_self[1000]:");
        typesTestQuery.queryZI2_by_self(this.api, 1000,
                v -> { query_file.println(v); });
        query_file.println("Query ZI2_by_const[]:");
        typesTestQuery.queryZI2_by_const(this.api,
                v -> { query_file.println(v); });

        query_file.println("Query ZI3_by_self[...]:");
        typesTestQuery.queryZI3_by_self(this.api,
                bldr -> {
                    return bldr.create_A("It's all Greek to me:  Α α, Β β, Γ γ, Δ δ, Ε ε, Ζ ζ, Η η, Θ θ, Ι ι, Κ κ, Λ λ, Μ μ, Ν ν, Ξ ξ, Ο ο, Π π, Ρ ρ, Σ σ/ς, Τ τ, Υ υ, Φ φ, Χ χ, Ψ ψ, Ω ω.");
                },
                v -> { query_file.println(printMany(v)); });
        query_file.println("Query ZI3_by_const[]:");
        typesTestQuery.queryZI3_by_const(this.api,
                v -> { query_file.println(printMany(v)); });

        query_file.println("Query ZI4_by_self[...]:");
        {
            ArrayList<String> strings = new ArrayList<String>();
            strings.add("Foo\n");
            strings.add("\tbar");
            typesTestQuery.queryZI4_by_self(this.api, strings,
                    v -> { query_file.println(printStrings(v)); });
        }

        query_file.println("Query ZI5_by_self[...]:");
        typesTestQuery.queryZI5_by_self(this.api,
                bldr -> {
                    ArrayList<Tuple2__string__ManyWriter> map = new ArrayList<Tuple2__string__ManyWriter>();
                    map.add(bldr.create_Tuple2__string__Many("key1", bldr.create_B(false)));
                    map.add(bldr.create_Tuple2__string__Many("key2", bldr.create_A("val2")));
                    return map;
                },
                v -> { query_file.println(printZI5(v)); });

        query_file.println("Query ZI6_by_self[\"ZI6\"]:");
        typesTestQuery.queryZI6_by_self(this.api,
                bldr -> {
                    return bldr.create_ddlog_std_Some__string("ZI6");
                },
                v -> { query_file.println(printOptString(v)); });
        query_file.println("Query ZI6_by_none[]:");
        typesTestQuery.queryZI6_by_none(this.api,
                v -> { query_file.println(printOptString(v)); });

        query_file.println("Query ZI7_by_self[\"♛\"]:");
        typesTestQuery.queryZI7_by_self(this.api, "♛",
                v -> { query_file.println("\"" + v + "\""); });
        query_file.println("Query ZI7_by_val[\"ZI7\"]:");
        typesTestQuery.queryZI7_by_val(this.api, "ZI7",
                v -> { query_file.println("\"" + v + "\""); });

        query_file.println("Query ZI8_by_self[100]:");
        typesTestQuery.queryZI8_by_self(this.api, 100,
                v -> { query_file.println(v); });

        query_file.println("Query ZI9_by_self[100]:");
        typesTestQuery.queryZI9_by_self(this.api, 100,
                v -> { query_file.println(v); });
        query_file.println("Query ZI9_by_refval[100]:");
        typesTestQuery.queryZI9_by_refval(this.api, 100,
                v -> { query_file.println(v); });
        query_file.println("Query ZI9_by_val[100]:");
        typesTestQuery.queryZI9_by_val(this.api, 100,
                v -> { query_file.println(v); });
        query_file.println("Query ZI9_by_const[]:");
        typesTestQuery.queryZI9_by_const(this.api,
                v -> { query_file.println(v); });

        query_file.println("Query ZI10_by_self[\"Ref<IString>\"]:");
        typesTestQuery.queryZI10_by_self(this.api, "Ref<IString>",
                v -> { query_file.println("\"" + v + "\""); });

        query_file.println("Query ZI11_by_self[\"val2\"=>\"v2\"]:");
        typesTestQuery.queryZI11_by_self(this.api,
                bldr -> {
                    ArrayList<Tuple2__Many__stringWriter> map = new ArrayList<Tuple2__Many__stringWriter>();
                    map.add(bldr.create_Tuple2__Many__string(bldr.create_A("val2"), "v2"));
                    return map;
                },
                v -> { query_file.println(printZI11(v)); });

        query_file.println("Query ZI12_by_self[..]:");
        typesTestQuery.queryZI12_by_self(this.api,
                bldr -> {
                    ArrayList<BigInteger> ints = new ArrayList<BigInteger>();
                    ints.add(BigInteger.valueOf(0));
                    ints.add(BigInteger.valueOf(0));
                    ints.add(BigInteger.valueOf(1));
                    return bldr.create_Tuple4__string__bigint__ddlog_std_Vec_bigint____bit_16___Many_(
                            "ZI12",
                            BigInteger.valueOf(1000000),
                            ints,
                            bldr.create_Tuple2__bit_16___Many(0x10,
                                bldr.create_D(bldr.create_Tuple3__bool__bit_8___string(false, (byte)2, "string"))));
                },
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Query ZI12_by_0[\"ZI12\"]:");
        typesTestQuery.queryZI12_by_0(this.api, "ZI12",
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Query ZI12_by_1[1000000]:");
        typesTestQuery.queryZI12_by_1(this.api, BigInteger.valueOf(1000000),
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Query ZI12_by_2[0,0,1]:");
        {
            ArrayList<BigInteger> ints = new ArrayList<BigInteger>();
            ints.add(BigInteger.valueOf(0));
            ints.add(BigInteger.valueOf(0));
            ints.add(BigInteger.valueOf(1));
            typesTestQuery.queryZI12_by_2(this.api, ints,
                    v -> { query_file.println(printZI12(v)); });
        }
        query_file.println("Query ZI12_by_3[...]:");
        typesTestQuery.queryZI12_by_3(this.api,
                bldr -> {
                    return bldr.create_Tuple2__bit_16___Many(0x10,
                            bldr.create_D(bldr.create_Tuple3__bool__bit_8___string(false, (byte)2, "string")));
                },
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Query ZI12_by_30[0x10]:");
        typesTestQuery.queryZI12_by_30(this.api, 0x10,
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Query ZI12_by_31[...]:");
        typesTestQuery.queryZI12_by_31(this.api,
                bldr -> {
                    return bldr.create_D(bldr.create_Tuple3__bool__bit_8___string(false, (byte)2, "string"));
                },
                v -> { query_file.println(printZI12(v)); });

        query_file.println("Query ZI13_by_f0[...]:");
        typesTestQuery.queryZI13_by_f0(this.api, "ZI13",
                v -> { query_file.println(printZI13(v)); });
        query_file.println("Query ZI13_by_f1[...]:");
        typesTestQuery.queryZI13_by_f1(this.api,
                bldr -> {
                    return bldr.create_Tuple3__bool__bit_8___string(false, (byte)2, "string");
                },
                v -> { query_file.println(printZI13(v)); });
        query_file.println("Query ZI13_by_f2[...]:");
        typesTestQuery.queryZI13_by_f2(this.api,
                bldr -> {
                    return bldr.create_A("ZI13");
                },
                v -> { query_file.println(printZI13(v)); });
        query_file.println("Query ZI13_by_t2[...]:");
        typesTestQuery.queryZI13_by_t2(this.api, "ZI13",
                v -> { query_file.println(printZI13(v)); });

        query_file.println("Query ZI14_by_self[...]:");
        typesTestQuery.queryZI14_by_self(this.api,
                bldr -> {
                    return bldr.create_First__string__signed_32_("string");
                },
                v -> { query_file.println(printCases("ZI14", v.c())); });
        query_file.println("Query ZI14_by_a[\"string\"]:");
        typesTestQuery.queryZI14_by_a(this.api, "string",
                v -> { query_file.println(printCases("ZI14", v.c())); });
        query_file.println("Query ZI14_by_b[5]:");
        typesTestQuery.queryZI14_by_b(this.api, 5,
                v -> { query_file.println(printCases("ZI14", v.c())); });

        query_file.println("Query ZI15_by_a[\"Or_string\"]:");
        typesTestQuery.queryZI15_by_a(this.api, "Or_string",
                v -> { query_file.println(printOr("ZI15", v.c())); });

        query_file.println("Query module_ZI16_by_x[\"zi16\"]:");
        typesTestQuery.querymodule_ZI16_by_x(this.api, "zi16",
                v -> { query_file.println("module_ZI16{\"" + v.x() + "\"}"); });

        query_file.println("Query module_ZI18_by_0[-1]:");
        typesTestQuery.queryZI18_by_0(this.api, -1,
                v -> { query_file.println("module_ZI18{" + printMTuple(v.t()) + "}"); });

        query_file.println("Query module_ZI19_by_1[\"zi19\"]:");
        typesTestQuery.querymodule_ZI19_by_1(this.api, "zi19",
                v -> { query_file.println(printMTuple(v)); });

        query_file.println("Query ZI20_by_0[-2]:");
        typesTestQuery.queryZI20_by_0(this.api, -2,
                v -> { query_file.println("ZI20{" + printMTuple(v.t()) + "}"); });

        query_file.println("Query ZI21_by_m[13]:");
        typesTestQuery.queryZI21_by_m(this.api, 13,
                v -> { query_file.println("ZI21{" + v.m() + "}"); });



        /* Dump everything. */
        query_file.println("Dump CI_by_c:");
        typesTestQuery.dumpCI_by_c(this.api, v -> {
            query_file.println("CI{" + v.c() + "}");
        });

        query_file.println("Dump DI_by_d:");
        typesTestQuery.dumpDI_by_d(this.api, v -> {
            query_file.println("DI{" + v.d() + "}");
        });
        query_file.println("Dump DI_by_none:");
        typesTestQuery.dumpDI_by_none(this.api, v -> {
            query_file.println("DI{" + v.d() + "}");
        });

        query_file.println("Dump EI_by_e:");
        typesTestQuery.dumpEI_by_e(this.api, v -> {
            query_file.println("EI{" + v.e() + "}");
        });
        query_file.println("Dump EO_by_e:");
        typesTestQuery.dumpEO_by_e(this.api, v -> {
            query_file.println("EO{" + v.e() + "}");
        });

        query_file.println("Dump FI_by_s:");
        typesTestQuery.dumpFI_by_s(this.api, v -> {
            query_file.println("FI{\"" + v.s() + "\"}");
        });

        query_file.println("Dump GI_by_d:");
        typesTestQuery.dumpGI_by_d(this.api, v -> {
            query_file.println("GI{" + v.d() + "}");
        });

        query_file.println("Dump HI_by_d:");
        typesTestQuery.dumpHI_by_d(this.api,  v -> {
            query_file.println("HI{" + v.d() + "}");
        });

        query_file.println("Dump II_by_d:");
        typesTestQuery.dumpII_by_d(this.api, v -> {
            query_file.println("II{" + v.d() + "}");
        });

        query_file.println("Dump JI_by_0:");
        typesTestQuery.dumpJI_by_0(this.api,  v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Dump JI_by_1:");
        typesTestQuery.dumpJI_by_1(this.api, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Dump JI_by_2:");
        typesTestQuery.dumpJI_by_2(this.api, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Dump JI_by_01:");
        typesTestQuery.dumpJI_by_01(this.api, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Dump JI_by_02:");
        typesTestQuery.dumpJI_by_02(this.api, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Dump JI_by_12:");
        typesTestQuery.dumpJI_by_12(this.api, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Dump JI_by_012:");
        typesTestQuery.dumpJI_by_012(this.api, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });
        query_file.println("Dump JI_by_all:");
        typesTestQuery.dumpJI_by_all(this.api,
                v -> {
                    query_file.println("JI{" + printTuple(v.a()) + "}");
                });
        query_file.println("Dump JI_by_self:");
        typesTestQuery.dumpJI_by_self(this.api,
                v -> {
                    query_file.println("JI{" + printTuple(v.a()) + "}");
                });
        query_file.println("Dump JI_by_10:");
        typesTestQuery.dumpJI_by_10(this.api, v -> {
            query_file.println("JI{" + printTuple(v.a()) + "}");
        });

        query_file.println("Dump KI_by_01:");
        typesTestQuery.dumpKI_by_01(this.api, v -> {
            query_file.println("KI{" + printTuple(v.t()) + "}");
        });
        query_file.println("Dump KI_by_all:");
        typesTestQuery.dumpKI_by_all(this.api,
                v -> {
                    query_file.println("KI{" + printTuple(v.t()) + "}");
                });

        query_file.println("Dump LI_by_01:");
        typesTestQuery.dumpLI_by_01(this.api, v -> {
            query_file.println(printTuple((Tuple3__bool__bit_8___stringReader)v));
        });
        query_file.println("Dump LI_by_all:");
        typesTestQuery.dumpLI_by_all(this.api,
                v -> {
                    query_file.println(printTuple((Tuple3__bool__bit_8___stringReader)v));
                });

        query_file.println("Dump L0I:");
        typesTestQuery.dumpL0I_by_a(this.api, v -> {
            query_file.println("L0I{" + v.a() + "," + v.b() + ",\"" + v.s() + "\"}");
        });

        query_file.println("Dump MI_by_v:");
        typesTestQuery.dumpMI_by_v(this.api, v -> {
            query_file.println("MI{" + v.v() + "}");
        });

        query_file.println("Dump NI_by_v:");
        typesTestQuery.dumpNI_by_v(this.api,
                v -> {
                    query_file.println(printNI(v));
                });

        query_file.println("Dump OI_by_v:");
        typesTestQuery.dumpOI_by_v(this.api,
                v -> {
                    query_file.println("OI{" + v.v() + "}");
                });

        query_file.println("Dump PI1_by_s:");
        typesTestQuery.dumpPI1_by_s(this.api, v -> {
            query_file.println("PI1{" + v.s() + "}");
        });

        query_file.println("Dump PI2_by_s:");
        typesTestQuery.dumpPI2_by_s(this.api, v -> {
            query_file.println("PI2{" + v.s() + "}");
        });

        query_file.println("Dump PI3_by_s:");
        typesTestQuery.dumpPI3_by_s(this.api, v -> {
            query_file.println("PI3{" + v.s() + "}");
        });

        query_file.println("Dump PI4_by_s:");
        typesTestQuery.dumpPI4_by_s(this.api, v -> {
            query_file.println("PI4{" + v.s() + "}");
        });
        query_file.println("Dump PI4_by_none:");
        typesTestQuery.dumpPI4_by_none(this.api, v -> {
            query_file.println("PI4{" + v.s() + "}");
        });
        query_file.println("Dump PI4_by_self:");
        typesTestQuery.dumpPI4_by_self(this.api,
                v -> {
                    query_file.println("PI4{" + v.s() + "}");
                });

        query_file.println("Dump PI5_by_s:");
        typesTestQuery.dumpPI5_by_s(this.api, v -> {
            query_file.println("PI5{" + v.s() + "}");
        });

        query_file.println("Dump QI_by_m:");
        typesTestQuery.dumpQI_by_m(this.api, v -> {
            query_file.println(printQI(v));
        });

        query_file.println("Dump RI_by_refm:");
        typesTestQuery.dumpRI_by_refm(this.api, v -> {
            query_file.println("RI{" + v.m() + "}");
        });
        query_file.println("Dump RI_by_m:");
        typesTestQuery.dumpRI_by_m(this.api, v -> {
            query_file.println("RI{" + v.m() + "}");
        });

        query_file.println("Dump SI_by_m:");
        typesTestQuery.dumpSI_by_m(this.api,
                v -> {
                    query_file.println("SI{C{\"" + v.m().x() + "\"}}");
                });
        query_file.println("Dump SI_by_x:");
        typesTestQuery.dumpSI_by_x(this.api,
                v -> {
                    query_file.println("SI{C{\"" + v.m().x() + "\"}}");
                });

        query_file.println("Dump TI_by_m:");
        typesTestQuery.dumpTI_by_m(this.api,
                v -> { query_file.println(printTI(v)); });
        query_file.println("Dump TI_by_some:");
        typesTestQuery.dumpTI_by_some(this.api,
                v -> { query_file.println(printTI(v)); });
        query_file.println("Dump TI_by_none:");
        typesTestQuery.dumpTI_by_none(this.api,
                v -> { query_file.println(printTI(v)); });

        query_file.println("Dump UI_by_x:");
        typesTestQuery.dumpUI_by_x(this.api,
                v -> { query_file.println(printMany(v)); });
        query_file.println("Dump UI_by_b:");
        typesTestQuery.dumpUI_by_b(this.api,
                v -> { query_file.println(printMany(v)); });
        query_file.println("Dump UI_by_t:");
        typesTestQuery.dumpUI_by_t(this.api,
                v -> { query_file.println(printMany(v)); });
        query_file.println("Dump UI_by_t1:");
        typesTestQuery.dumpUI_by_t1(this.api,
                v -> { query_file.println(printMany(v)); });

        query_file.println("Dump VI_by_a:");
        typesTestQuery.dumpVI_by_a(this.api,
                v -> {
                    query_file.println("VI{" + v.a() + "," + printMany(v.b()) + "}");
                });
        query_file.println("Dump VI_by_t1:");
        typesTestQuery.dumpVI_by_t1(this.api,
                v -> {
                    query_file.println("VI{" + v.a() + "," + printMany(v.b()) + "}");
                });

        query_file.println("Dump WI_by_t2:");
        typesTestQuery.dumpWI_by_t2(this.api,
                v -> { query_file.println(printWI(v)); });
        query_file.println("Dump WI_by_t:");
        typesTestQuery.dumpWI_by_t(this.api,
                v -> { query_file.println(printWI(v)); });

        query_file.println("Dump XI_by_m:");
        typesTestQuery.dumpXI_by_m(this.api,
                v -> { query_file.println(printXI(v)); });

        query_file.println("Dump YI_by_v:");
        typesTestQuery.dumpYI_by_v(this.api,
                v -> { query_file.println(printYI(v)); });
        query_file.println("Dump YI_by_none:");
        typesTestQuery.dumpYI_by_none(this.api,
                v -> { query_file.println(printYI(v)); });
        query_file.println("Dump YI_by_self:");
        typesTestQuery.dumpYI_by_self(this.api,
                v -> { query_file.println(printYI(v)); });

        query_file.println("Dump ZI_by_d:");
        typesTestQuery.dumpZI_by_d(this.api,
                v -> { query_file.println("HI{" + v.d() + "}"); });

        query_file.println("Dump ZI0_by_self:");
        typesTestQuery.dumpZI0_by_self(this.api,
                v -> { query_file.println("\"" + v + "\""); });

        query_file.println("Dump ZI1_by_self:");
        typesTestQuery.dumpZI1_by_self(this.api,
                v -> { query_file.println(v); });
        query_file.println("Dump ZI1_by_true:");
        typesTestQuery.dumpZI1_by_true(this.api,
                v -> { query_file.println(v); });

        query_file.println("Dump ZI2_by_self:");
        typesTestQuery.dumpZI2_by_self(this.api,
                v -> { query_file.println(v); });
        query_file.println("Dump ZI2_by_const:");
        typesTestQuery.dumpZI2_by_const(this.api,
                v -> { query_file.println(v); });

        query_file.println("Dump ZI3_by_self:");
        typesTestQuery.dumpZI3_by_self(this.api,
                v -> { query_file.println(printMany(v)); });
        query_file.println("Dump ZI3_by_const:");
        typesTestQuery.dumpZI3_by_const(this.api,
                v -> { query_file.println(printMany(v)); });

        query_file.println("Dump ZI4_by_self:");
        typesTestQuery.dumpZI4_by_self(this.api,
                v -> { query_file.println(printStrings(v)); });

        query_file.println("Dump ZI5_by_self:");
        typesTestQuery.dumpZI5_by_self(this.api,
                v -> { query_file.println(printZI5(v)); });

        query_file.println("Dump ZI6_by_self:");
        typesTestQuery.dumpZI6_by_self(this.api,
                v -> { query_file.println(printOptString(v)); });
        query_file.println("Dump ZI6_by_none:");
        typesTestQuery.dumpZI6_by_none(this.api,
                v -> { query_file.println(printOptString(v)); });

        query_file.println("Dump ZI7_by_self:");
        typesTestQuery.dumpZI7_by_self(this.api,
                v -> { query_file.println("\"" + v + "\""); });
        query_file.println("Dump ZI7_by_val:");
        typesTestQuery.dumpZI7_by_val(this.api,
                v -> { query_file.println("\"" + v + "\""); });

        query_file.println("Dump ZI8_by_self:");
        typesTestQuery.dumpZI8_by_self(this.api,
                v -> { query_file.println(v); });

        query_file.println("Dump ZI9_by_self:");
        typesTestQuery.dumpZI9_by_self(this.api,
                v -> { query_file.println(v); });
        query_file.println("Dump ZI9_by_refval:");
        typesTestQuery.dumpZI9_by_refval(this.api,
                v -> { query_file.println(v); });
        query_file.println("Dump ZI9_by_val:");
        typesTestQuery.dumpZI9_by_val(this.api,
                v -> { query_file.println(v); });
        query_file.println("Dump ZI9_by_const:");
        typesTestQuery.dumpZI9_by_const(this.api,
                v -> { query_file.println(v); });

        query_file.println("Dump ZI10_by_self:");
        typesTestQuery.dumpZI10_by_self(this.api,
                v -> { query_file.println("\"" + v + "\""); });

        query_file.println("Dump ZI11_by_self:");
        typesTestQuery.dumpZI11_by_self(this.api,
                v -> { query_file.println(printZI11(v)); });

        query_file.println("Dump ZI12_by_self:");
        typesTestQuery.dumpZI12_by_self(this.api,
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Dump ZI12_by_0:");
        typesTestQuery.dumpZI12_by_0(this.api,
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Dump ZI12_by_1:");
        typesTestQuery.dumpZI12_by_1(this.api,
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Dump ZI12_by_2:");
        typesTestQuery.dumpZI12_by_2(this.api,
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Dump ZI12_by_3:");
        typesTestQuery.dumpZI12_by_3(this.api,
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Dump ZI12_by_30:");
        typesTestQuery.dumpZI12_by_30(this.api,
                v -> { query_file.println(printZI12(v)); });
        query_file.println("Dump ZI12_by_31:");
        typesTestQuery.dumpZI12_by_31(this.api,
                v -> { query_file.println(printZI12(v)); });

        query_file.println("Dump ZI13_by_f0:");
        typesTestQuery.dumpZI13_by_f0(this.api,
                v -> { query_file.println(printZI13(v)); });
        query_file.println("Dump ZI13_by_f1:");
        typesTestQuery.dumpZI13_by_f1(this.api,
                v -> { query_file.println(printZI13(v)); });
        query_file.println("Dump ZI13_by_f2:");
        typesTestQuery.dumpZI13_by_f2(this.api,
                v -> { query_file.println(printZI13(v)); });
        query_file.println("Dump ZI13_by_t2:");
        typesTestQuery.dumpZI13_by_t2(this.api,
                v -> { query_file.println(printZI13(v)); });

        query_file.println("Dump ZI14_by_self:");
        typesTestQuery.dumpZI14_by_self(this.api,
                v -> { query_file.println(printCases("ZI14", v.c())); });
        query_file.println("Dump ZI14_by_a:");
        typesTestQuery.dumpZI14_by_a(this.api,
                v -> { query_file.println(printCases("ZI14", v.c())); });
        query_file.println("Dump ZI14_by_b:");
        typesTestQuery.dumpZI14_by_b(this.api,
                v -> { query_file.println(printCases("ZI14", v.c())); });

        query_file.println("Dump ZI15_by_a:");
        typesTestQuery.dumpZI15_by_a(this.api,
                v -> { query_file.println(printOr("ZI15", v.c())); });

        query_file.println("Dump module_ZI16_by_x:");
        typesTestQuery.dumpmodule_ZI16_by_x(this.api,
                v -> { query_file.println("module_ZI16{\"" + v.x() + "\"}"); });

        query_file.println("Dump module_ZI18_by_0:");
        typesTestQuery.dumpZI18_by_0(this.api,
                v -> { query_file.println("module_ZI18{" + printMTuple(v.t()) + "}"); });

        query_file.println("Dump module_ZI19_by_1:");
        typesTestQuery.dumpmodule_ZI19_by_1(this.api,
                v -> { query_file.println(printMTuple(v)); });

        query_file.println("Dump ZI20_by_0:");
        typesTestQuery.dumpZI20_by_0(this.api,
                v -> { query_file.println("ZI20{" + printMTuple(v.t()) + "}"); });

        query_file.println("Dump ZI21_by_m:");
        typesTestQuery.dumpZI21_by_m(this.api,
                v -> { query_file.println("ZI21{" + v.m() + "}"); });


        this.fb_file.close();
        this.query_file.close();

        String profile_fname = this.api.dumpProfile();
        System.out.println("Profile written to '" + profile_fname + "'");
        String size_profile = this.api.arrangementSizeProfile();
        Files.write(Paths.get("arrangement_size_profile.json"), size_profile.getBytes());
        System.out.println("Arrangement size profile written to 'arrangement_size_profile.json'");
        String peak_profile = this.api.peakArrangementSizeProfile();
        Files.write(Paths.get("peak_arrangement_size_profile.json"), peak_profile.getBytes());
        System.out.println("Peak arrangement size profile written to 'peak_arrangement_size_profile.json'");
        String change_profile = this.api.changeProfile();
        Files.write(Paths.get("change_profile.json"), change_profile.getBytes());
        System.out.println("Change profile written to 'change_profile.json'");
        String cpu_profile = this.api.cpuProfile();
        Files.write(Paths.get("cpu_profile.json"), cpu_profile.getBytes());
        System.out.println("CPU profile written to 'cpu_profile.json'");

    }

    public static void main(String[] args) throws IOException, DDlogException {
        Test test = new Test();
        test.run();
    }
}
